package io.renren.modules.websocket;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;

@Api(description = "websocket接口")
@Component
//访问服务端的url地址
@ServerEndpoint(value = "/websocket/{id}")
public class WebSocketServer {
    private static int onlineCount = 0;
    //加了@Component注解在初始化这个WebSocketServer类的时候，会在启动的时候就把这个类里面的static 变量方法都加载好
    //并且 当有新的连接进来的时候不会再次定义这个ConcurrentHashMap的静态变量。
    //private static ConcurrentHashMap<String, WebSocketServer> webSocketSet = new ConcurrentHashMap<>();
    private static CopyOnWriteArraySet<WebSocketServer> webSocketSet = new CopyOnWriteArraySet<>();
    //与某个客户端的连接会话，需要通过它来给客户端发送数据
    private Session session;
    private static Logger log = LogManager.getLogger(WebSocketServer.class);
    private String id = "";
    /**
     * 连接建立成功调用的方法
     *  id为用户的userId
     * */
    //当很多不同的用户连进来的时候就会有 很多不同websocket类，但他们getWebSocketSessions 都是取到同一个static的websocket
   /* public ConcurrentHashMap<String, WebSocketServer> getWebSocketSessions(){
        //这里return 也是return 静态变量。
        //即使 生成了很多websocketserver 这个类，但是他们的static变量，都是指针指过去的。
        return webSocketSet;
    }
*/

    @ApiOperation(value = "onopen",notes = "onopen")
    @OnOpen
    public void onOpen(@PathParam(value = "id") String id, Session session) {
        this.session = session;
        this.id = id;//接收到发送消息的人员编号 //每次有用户连接进来都会调用这个方法。也可以在此基础上做一个哪些用户在线的场景
        webSocketSet.add(this);     //加入set中
        addOnlineCount();           //在线数加1
        log.info("用户"+id+"加入！当前在线人数为" + getOnlineCount());
        System.out.println("用户"+id+"加入！当前在线人数为" + getOnlineCount());

    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose() {
        webSocketSet.remove(this);  //从set中删除
        subOnlineCount();           //在线数减1
        log.info("有一连接关闭！当前在线人数为" + getOnlineCount());
        System.out.println("有一连接关闭！当前在线人数为" + getOnlineCount());
    }

    /**
     * 收到客户端消息后调用的方法
     *
     * @param message 客户端发送过来的消息*/
    @OnMessage
    public void onMessage(String message, Session session) {
        log.info("来自客户端的消息:" + message);
        //可以自己约定字符串内容，比如 内容|0 表示信息群发，内容|X 表示信息发给id为X的用户
        String sendMessage = message;
        String sendUserId = "0";
        /*try {
            if(sendUserId.equals("0")){

            }
            else{
                sendtoUser(sendMessage,sendUserId);

            }
        } catch (IOException e) {
            e.printStackTrace();
        }*/

    }

    /**
     *
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session, Throwable error) {
        log.error("发生错误");
        error.printStackTrace();
    }


    public void sendMessage(String message) throws IOException {
        this.session.getBasicRemote().sendText(message);
    }

    /**
     * 发送信息给指定ID用户，如果用户不在线则返回不在线信息给自己
     * @param message
     * @param sendUserId
     * @throws IOException
     */
    /*public void sendtoUser(String message,String sendUserId) throws IOException {
        if (webSocketSet.get(sendUserId) != null) {
            if(!id.equals(sendUserId)){
                webSocketSet.get(sendUserId).sendMessage( "用户" + id + "发来消息：" + " <br/> " + message);
            }
            else{
                webSocketSet.get(sendUserId).sendMessage(message);
            }
        }
    }*/

    /**
     * 发送信息给所有人
     * @param message
     * @throws IOException
     */
    public void sendtoAll(String message) throws IOException {
        try {
            if (webSocketSet.size()!=0){
                for (WebSocketServer p:webSocketSet){
                    if (p!=null){
                        p.session.getBasicRemote().sendText(message);
                        log.info(message);
                    }
                }
            }
        }catch (IOException e){
            e.printStackTrace();
        }
        /*for (String key : webSocketSet.keySet()) {
            try {
                webSocketSet.get(key).sendMessage(message);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }*/
    }


    public static synchronized int getOnlineCount() {
        return onlineCount;
    }

    public static synchronized void addOnlineCount() {
        WebSocketServer.onlineCount++;
    }

    public static synchronized void subOnlineCount() {
        WebSocketServer.onlineCount--;
    }

    public Session getSession(){
        return this.session;
    }

}

